﻿using SqlSugar;
using SqlSugarAndEntity.Entity;
using SqlSugarAndEntity.Base;
using SqlSugarAndEntity.Extension;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using static SqlSugarAndEntity.Extension.DataModel;
using Core.AutoFacService.Attributes.InjectAttributes;

namespace Repository.Base
{
    [Inject]
    public class BaseRepository<T> : IBaseRepository<T> where T : class, new()
    {
        private IBaseMethod _baseMethod;
        public BaseRepository(IBaseMethod baseMethod)
        {
            _baseMethod = baseMethod;
        }
        public ISqlSugarClient GetSqlSugarClient()
        {
            return _baseMethod.Db();
        }
        #region 同步操作实现
        public virtual bool Delete(T entity)
        {
            return _baseMethod.Db().Deleteable(entity).ExecuteCommand() > 0;
        }
        public virtual bool Delete(Expression<Func<T, bool>> WhereExp)
        {
            return _baseMethod.Db().Deleteable<T>().Where(WhereExp).ExecuteCommand()>0;
        }
        public virtual void Delete(List<T> list)
        {
            _baseMethod.Db().Deleteable(list).ExecuteCommand();
        }

        public virtual int ExecuteSqlCommand(string sql)
        {
            return _baseMethod.Db().Ado.ExecuteCommand(sql);
        }

        public virtual DataTable FromSql(string sql)
        {
            return _baseMethod.Db().Ado.GetDataTable(sql);
        }

        public virtual List<T> GetInfo(Expression<Func<T, bool>> predicate)
        {       
            return _baseMethod.Db().Queryable<T>().WhereIF(predicate!=null, predicate).ToList();
        }

        public virtual PageListModel<T> GetInfoByPage(Expression<Func<T, bool>> predicate, int page, int limit)
        {
            return _baseMethod.Db().Queryable<T>().WhereIF(predicate!=null, predicate).ToPageModel(page,limit);
        }
        public virtual List<T> GetOrderbyAscInfo(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderBy)
        {
            return _baseMethod.Db().Queryable<T>().WhereIF(predicate != null, predicate).OrderByIF(orderBy!=null, orderBy).ToList();
        }
        public virtual List<T> GetOrderbyDescInfo(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderBy)
        {
            return _baseMethod.Db().Queryable<T>().WhereIF(predicate != null, predicate).OrderByIF(orderBy != null, orderBy,OrderByType.Desc).ToList();
        }

        public virtual PageListModel<T> GetOrderbyAscInfoByPage(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderBy, int page, int limit)
        {
            return _baseMethod.Db().Queryable<T>().WhereIF(predicate != null, predicate).OrderByIF(orderBy!=null, orderBy).ToPageModel(page, limit);
        }
        public virtual PageListModel<T> GetOrderbyDescInfoByPage(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderBy, int page, int limit)
        {
            return _baseMethod.Db().Queryable<T>().WhereIF(predicate != null, predicate).OrderByIF(orderBy != null, orderBy, OrderByType.Desc).ToPageModel(page, limit);
        }
        public virtual DataTable GetInfoToDataTable(Expression<Func<T, bool>> predicate)
        {
            return _baseMethod.Db().Queryable<T>().WhereIF(predicate != null, predicate).ToDataTable();
        }
        public virtual PageDataTable GetInfoToDataTableByPage(Expression<Func<T, bool>> predicate, int page, int limit)
        {
            return _baseMethod.Db().Queryable<T>().WhereIF(predicate != null, predicate).ToPageDT(page,limit);
        }
        public virtual bool Insert(T entity)
        {
            return _baseMethod.Db().Insertable(entity).ExecuteCommand()>0;
        }

        public virtual bool Insert(List<T> list)
        {
            return _baseMethod.Db().Insertable(list).ExecuteCommand()>0;
        }
        public bool InsertIgnoreColumns(T entity, Expression<Func<T, object>> IgnoreColumns)
        {
            return _baseMethod.Db().Insertable(entity).IgnoreColumns(IgnoreColumns).ExecuteCommand() > 0;
        }

        public bool InsertAppiontColumns(T entity, Expression<Func<T, object>> AppiontColumns)
        {
            return _baseMethod.Db().Insertable(entity).InsertColumns(AppiontColumns).ExecuteCommand() > 0;
        }

        public virtual bool Update(T entity)
        {
            return _baseMethod.Db().Updateable(entity).ExecuteCommand() > 0;
        }
        public virtual bool Update(T entity,Expression<Func<T,object>> WhereSelect)
        {
            return _baseMethod.Db().Updateable(entity).WhereColumns(WhereSelect).ExecuteCommand() > 0;
        }
        public virtual bool Update(Expression<Func<T, T>> SetColumns, Expression<Func<T, bool>> WhereCondition=null)
        {
            if (WhereCondition != null)
            {
                return _baseMethod.Db().Updateable(SetColumns).Where(WhereCondition).ExecuteCommand() > 0;
            }
            else
            {
                return _baseMethod.Db().Updateable(SetColumns).ExecuteCommand() > 0;
            }
           
        }
        public virtual bool UpdateIgnoreColumns(T entity, Expression<Func<T, object>> WhereSelect, Expression<Func<T,object>>IgnoreExpress)
        {
            return _baseMethod.Db().Updateable(entity).IgnoreColumns(IgnoreExpress).WhereColumns(WhereSelect).ExecuteCommand() > 0;
        }
        public virtual bool UpdateAppiontColumns(T entity, Expression<Func<T, object>> WhereSelect, Expression<Func<T, object>> UpdateExpress)
        {
            return _baseMethod.Db().Updateable(entity).UpdateColumns(UpdateExpress).WhereColumns(WhereSelect).ExecuteCommand() > 0;
        }

        public virtual bool Update(List<T> list)
        {
            return _baseMethod.Db().Updateable(list).ExecuteCommand()>0;
        }
        public virtual bool Update(List<T> list, Expression<Func<T, object>> WhereExp)
        {
            return _baseMethod.Db().Updateable(list).WhereColumns(WhereExp).ExecuteCommand()>0;
        }
        public virtual void SaveOrUpdate(List<T> list, Expression<Func<T, object>> SaveExpress = null)
        {
            var db = _baseMethod.Db();
            StorageableResult<T> x = null;
            if (SaveExpress != null)
            {
                x = db.Storageable(list).WhereColumns(SaveExpress).ToStorage();
            }
            else
            {
                x = db.Storageable(list).ToStorage();
            }
            x.AsInsertable.ExecuteCommand();
            x.AsUpdateable.ExecuteCommand();
        }
        public virtual void SaveOrUpdate(List<T> list, Expression<Func<T, object>> SaveExpress = null, Action<StorageableResult<T>> func = null)
        {
            var db = _baseMethod.Db();
            StorageableResult<T> x = null;
            if (SaveExpress != null)
            {
                x = db.Storageable(list).WhereColumns(SaveExpress).ToStorage();
            }
            else
            {
                x = db.Storageable(list).ToStorage();
            }
            func.Invoke(x);
        }

        public virtual void BeginTran(Action<ISqlSugarClient> action)
        {
            var db= _baseMethod.Db();
            try
            {
                db.Ado.BeginTran();
                action.Invoke(db);
                db.Ado.CommitTran();
            }
            catch(Exception e)
            {
                db.Ado.RollbackTran();
                throw new Exception(e.Message);
            }
        }
        public virtual bool BulkCopy(List<T> list)
        {
            return _baseMethod.Db().Fastest<T>().BulkCopy(list)>0;
        }
        public virtual bool BulkUpdate(List<T> list)
        {
            return _baseMethod.Db().Fastest<T>().BulkUpdate(list) > 0;
        }
        public virtual bool BulkUpdate(List<T> list,IEnumerable<string> WhereColumn, IEnumerable<string> UpdateColumn)
        {
            string[] WhereColumns=WhereColumn.ToArray();
            string[] UpdateColumns=UpdateColumn.ToArray();
            return _baseMethod.Db().Fastest<T>().BulkUpdate(list,WhereColumns,UpdateColumns) > 0;
        }


        #endregion
        #region 异步方法实现
        public virtual async Task<bool> InsertSync(T entity)
        {
            return await _baseMethod.Db().Insertable(entity).ExecuteCommandAsync() > 0;
        }

        public virtual async Task<bool> InsertIgnoreColumnsSync(T entity, Expression<Func<T, object>> IgnoreColumns)
        {
            return await _baseMethod.Db().Insertable(entity).IgnoreColumns(IgnoreColumns).ExecuteCommandAsync() > 0;
        }

        public virtual async Task<bool> InsertAppiontColumnsSync(T entity, Expression<Func<T, object>> AppiontColumns)
        {
            return await _baseMethod.Db().Insertable(entity).InsertColumns(AppiontColumns).ExecuteCommandAsync() > 0;
        }

        public virtual async Task<bool> UpdateSync(T entity)
        {
            return await _baseMethod.Db().Updateable(entity).ExecuteCommandAsync() > 0;
        }

        public virtual async Task<bool> UpdateSync(T entity, Expression<Func<T, object>> WhereSelect)
        {
            return await _baseMethod.Db().Updateable(entity).WhereColumns(WhereSelect).ExecuteCommandAsync() > 0;
        }

        public virtual async Task<bool> UpdateSync(Expression<Func<T, T>> SetColumns, Expression<Func<T, bool>> WhereCondition)
        {
            return await _baseMethod.Db().Updateable<T>().SetColumns(SetColumns).Where(WhereCondition).ExecuteCommandAsync() > 0;
        }

        public virtual async Task<bool> UpdateIgnoreColumnsSync(T entity, Expression<Func<T, object>> WhereSelect, Expression<Func<T, object>> IgnoreExpress)
        {
            return await _baseMethod.Db().Updateable(entity).WhereColumns(WhereSelect).IgnoreColumns(IgnoreExpress).ExecuteCommandAsync() > 0;
        }

        public virtual async Task<bool> UpdateAppiontColumnsSync(T entity, Expression<Func<T, object>> WhereSelect, Expression<Func<T, object>> UpdateExpress)
        {
            return await _baseMethod.Db().Updateable(entity).WhereColumns(WhereSelect).UpdateColumns(UpdateExpress).ExecuteCommandAsync() > 0;
        }

        public virtual async Task<bool> DeleteSync(T entity)
        {
            return await _baseMethod.Db().Deleteable(entity).ExecuteCommandAsync() > 0;
        }

        public virtual async Task<bool> DeleteSync(Expression<Func<T, bool>> WhereExp)
        {
            return await _baseMethod.Db().Deleteable<T>().Where(WhereExp).ExecuteCommandAsync() > 0;
        }

        public virtual async Task<List<T>> GetInfoSync(Expression<Func<T, bool>> predicate)
        {
            return await _baseMethod.Db().Queryable<T>().WhereIF(predicate!=null, predicate).ToListAsync();
        }

        public virtual async Task<List<T>> GetOrderbyAscInfoSync(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderBy)
        {
            return await _baseMethod.Db().Queryable<T>().WhereIF(predicate!=null, predicate).OrderBy(orderBy).ToListAsync();
        }

        public virtual async Task<List<T>> GetOrderbyDescInfoSync(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderBy)
        {
            return await _baseMethod.Db().Queryable<T>().WhereIF(predicate != null, predicate).OrderBy(orderBy,OrderByType.Desc).ToListAsync();
        }

        public virtual async Task<PageListModel<T>> GetInfoByPageSync(Expression<Func<T, bool>> predicate, int page, int limit)
        {
            return await _baseMethod.Db().Queryable<T>().WhereIF(predicate != null, predicate).ToPageModelSync(page,limit);
        }

        public virtual async Task<PageListModel<T>> GetOrderbyAscInfoByPageSync(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderBy, int page, int limit)
        {
            return await _baseMethod.Db().Queryable<T>().WhereIF(predicate != null, predicate).OrderByIF(orderBy != null, orderBy).ToPageModelSync(page, limit);
        }

        public virtual async Task<PageListModel<T>> GetOrderbyDescInfoByPageSync(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderBy, int page, int limit)
        {
            return await _baseMethod.Db().Queryable<T>().WhereIF(predicate != null, predicate).OrderByIF(orderBy != null, orderBy,OrderByType.Desc).ToPageModelSync(page, limit);
        }

        public virtual async Task<DataTable> FromSqlSync(string sql)
        {
            return await _baseMethod.Db().Ado.GetDataTableAsync(sql);
        }

        

        public virtual async Task InsertSync(List<T> list)
        {
            await _baseMethod.Db().Insertable(list).ExecuteCommandAsync();
        }

        public virtual async Task DeleteSync(List<T> list)
        {
            await _baseMethod.Db().Deleteable(list).ExecuteCommandAsync();
        }

        public virtual async Task UpdateSync(List<T> list)
        {
            await _baseMethod.Db().Updateable(list).ExecuteCommandAsync();
        }

        public virtual async Task UpdateSync(List<T> list, Expression<Func<T, object>> WhereExp)
        {
            await _baseMethod.Db().Updateable(list).WhereColumns(WhereExp).ExecuteCommandAsync();
        }

        public virtual async Task<DataTable> GetInfoToDataTableSync(Expression<Func<T, bool>> predicate)
        {
            return await _baseMethod.Db().Queryable<T>().Where(predicate).ToDataTableAsync();
        }

        public virtual async Task<int> ExecuteSqlCommandSync(string sql)
        {
            return await _baseMethod.Db().Ado.ExecuteCommandAsync(sql);
        }

        public virtual async Task<bool> BulkCopySync(List<T> list)
        {
            return await _baseMethod.Db().Fastest<T>().BulkCopyAsync(list) > 0;
        }
        public virtual async Task<bool> BulkUpdateSync(List<T> list)
        {
            return await _baseMethod.Db().Fastest<T>().BulkUpdateAsync(list) > 0;
        }
        public virtual async Task<bool> BulkUpdateSync(List<T> list, IEnumerable<string> WhereColumn, IEnumerable<string> UpdateColumn)
        {
            string[] WhereColumns = WhereColumn.ToArray();
            string[] UpdateColumns = UpdateColumn.ToArray();
            return await _baseMethod.Db().Fastest<T>().BulkUpdateAsync(list, WhereColumns, UpdateColumns) > 0;
        }

        




        #endregion
    }
}
